
#ifndef RT_DETECT_CONNECTOR_H
#define RT_DETECT_CONNECTOR_H

#include "RtConnectionInterface.h"
#include "RtReferenceControl.h"
#include "RtInetAddr.h"
#include "RtTimeValue.h"
#include <list>

#define TOP_PRIORITY					1
#define CONNECTOR_STATUS_UNCONNECTED	0x0001
#define CONNECTOR_STATUS_CONNECTED		0x0002

///////////////////////////////////////////
//class CRtDetectionConnector
///////////////////////////////////////////
class /*RT_API_EXPORT*/ CRtDetectionConnector : 
	public IRtDetectionConnector, 
	public CRtReferenceControlSingleThreadTimerDelete
	,public CRtTimerWrapperSink
{
	class CConnectorItem;
	friend class CConnectorItem;
	typedef std::list<CRtAutoPtr<CConnectorItem> >::iterator iter_type;
public:
	/// add connection one by one, and the prior has high priority.
	virtual RtResult AddConnection(
		CRtConnectionManager::CType Type, 
		const CRtInetAddr &aAddrPeer,
		CRtTimeValue *aTimeDelay);
	
	/// Start connecting at the same time in <aTimeout>,
	/// If low priority connection connected, wait high priority connection in <aTimeDelay>.
	virtual void StartDetectionConnect(
		IRtAcceptorConnectorSink *aSink,
		CRtTimeValue *aTimeout = NULL,
		DetectMode inMode = DETECT_CONCURRENT,
		CRtInetAddr *aAddrLocal = NULL);
	
	virtual void AsycConnect(
		IRtAcceptorConnectorSink *aSink,
		const CRtInetAddr &aAddrPeer, 
		CRtTimeValue *aTimeout = NULL,
		CRtInetAddr *aAddrLocal = NULL);
	
	virtual void CancelConnect();

	virtual BOOL IsConnector();
	virtual void OnTimer(CRtTimerWrapper* aId);
protected:
	// Cancel all Connect except pExclude.
	virtual void CancelConnect(CConnectorItem* pExclude);
	void OnConnectFailed();
public:
	CRtDetectionConnector();
	virtual ~CRtDetectionConnector();
public:	
	virtual DWORD AddReference()
	{
		return CRtReferenceControlSingleThreadTimerDelete::AddReference();
	};
	
	virtual DWORD ReleaseReference()
	{
		return CRtReferenceControlSingleThreadTimerDelete::ReleaseReference();
	};
private:
	
	//Inner class, items of m_conn_list
	class CConnectorItem : 
		public IRtAcceptorConnectorSink, 
		public CRtReferenceControlSingleThread//,
		//public CRtTimerWrapperSink
	{
		friend class CRtDetectionConnector;
	public:
		CConnectorItem(
			IRtConnector *pIRtConnector,
			CRtConnectionManager::CType aType, 
			WORD wPriority, 
			CRtInetAddr aAddrPeer, 
			CRtDetectionConnector* pOuterClass,
			CRtTimeValue* aTimeDelay);

		~CConnectorItem();

		void AsycConnect(
			CRtTimeValue *aTimeout = NULL,
			CRtInetAddr *aAddrLocal = NULL);
		void CancelConnect();
	public:
		void IsAllFailed(RtResult aReason);
		
		virtual void OnConnectIndication(
			RtResult aReason,
			IRtTransport *aTrpt,
			IRtAcceptorConnectorId *aRequestId);
		
		//void OnTimer(CRtTimerWrapper* aId);
	public:	
		virtual DWORD AddReference()
		{
			return CRtReferenceControlSingleThread::AddReference();
		};
		
		virtual DWORD ReleaseReference()
		{
			return CRtReferenceControlSingleThread::ReleaseReference();
		};
		
		WORD GetStatus()
		{
			return m_wStatus;
		}

		void SetStatus(WORD wStatus)
		{
			m_wStatus = wStatus;
		}

		void SetAddrPeer(const CRtInetAddr &aAddr)
		{
			m_aAddrPeer = aAddr;
		}
		BOOL IsConnected() const{return m_bStart;}
	private:
		CRtAutoPtr<IRtConnector> m_pConnector;
		RtResult m_aReason;									//Reason from TP Layer
		CRtAutoPtr<IRtTransport> m_pITransport;			//Transport from TP layer
		CRtConnectionManager::CType m_aType;
		WORD m_wPriority;
		CRtInetAddr m_aAddrPeer;
		CRtDetectionConnector* m_pOuterClass;
		
		//CRtTimerWrapper m_Timer;	

		WORD m_wStatus;
		
		//CRtTimeValue m_TimeDelay;
		BOOL m_bStart;
	};

private:
	WORD m_wPriority;
	//BOOL m_bGetHighestPriority;								//Get the highest priority connection
	std::list<CRtAutoPtr<CConnectorItem> > m_conn_list;
	IRtAcceptorConnectorSink *m_aSink;						//Connector Sink from Upper layer

	CRtAutoPtr<IRtConnector> m_pChampionConnector;		//Final champion connector
	DWORD m_dwConnFailedCnt;								//How many conneciton failed
	DWORD m_dwConnAddCnt;									//how many connection added
	CRtTimerWrapper m_Timer;
	CRtTimeValue m_timeout; 
	CRtInetAddr m_localAddr;
};

#endif	//RT_DETECT_CONNECTOR_H
